#include "CI2C.h"

uint32 _SCL;
uint32 _SDA;


void I2C_Init(uint32 SCL, uint32 SDA)
{
	pinMode(_SCL, OUTPUT);
	pinMode(_SDA, OUTPUT);
	digitalWrite(_SCL, HIGH);
	digitalWrite(_SDA, HIGH);
	_SCL = SCL;
	_SDA = SDA;
};


void Start()
{
	digitalWrite(_SDA, HIGH);
	digitalWrite(_SCL, HIGH);
	digitalWrite(_SDA, LOW);
	digitalWrite(_SCL, LOW);

};
void End()
{
	digitalWrite(_SCL, LOW);
	digitalWrite(_SDA, LOW);
	digitalWrite(_SCL, HIGH);
	digitalWrite(_SDA, HIGH);
};

void Ack()
{
	digitalWrite(_SDA, LOW);
	digitalWrite(_SCL, HIGH);
	digitalWrite(_SCL, LOW);
}

void NoAck()
{
	digitalWrite(_SDA, HIGH);
	digitalWrite(_SCL, HIGH);
	digitalWrite(_SCL, LOW);
}




BOOL SendByte(uint8 data)
{
	for (size_t i = 0x80; i > 0; i >>= 1)
	{
		if (data & i)
			digitalWrite(_SDA, HIGH);
		else
			digitalWrite(_SDA, LOW);

		digitalWrite(_SCL, HIGH);
		digitalWrite(_SCL, LOW);
	}
	pinMode(_SDA, INPUT);
	digitalWrite(_SCL, HIGH);
	BOOL res = digitalRead(_SDA);
	pinMode(_SDA, OUTPUT);
	digitalWrite(_SCL, LOW);
	return res;
}

uint8 ReadByte(BOOL ACK)
{

	pinMode(_SDA, INPUT_PULLUP);
	uint8 data = 0;
	for (size_t i = 0x80; i > 0; i >>= 1)
	{
		digitalWrite(_SCL, LOW);
		digitalWrite(_SCL, HIGH);
		if (digitalRead(_SDA))
			data |= i;
	}
	digitalWrite(_SCL, LOW);
	pinMode(_SDA, OUTPUT);

	if (ACK)
		Ack();
	else
		NoAck();
	return data;
}




BOOL I2C_SendAddByte(uint8 addr, uint8 regaddr, uint8 data)
{
	Start();

	if (SendByte((addr << 1) | 0x00))
		goto end;

	if (SendByte(regaddr))
		goto end;

	if (SendByte(data))
		goto end;

	End();
	return True;
end:
	End();
	return False;
}

BOOL I2C_ReadAddByte(uint8 addr, uint8 regaddr, uint8* data)
{
	Start();

	if (SendByte((addr << 1) | 0x00))
		goto end;

	if (SendByte(regaddr))
		goto end;

	Start();

	if (SendByte((addr << 1) | 0x01))
		goto end;

	*data = ReadByte(False);

	End();
	return True;
end:
	End();
	return False;
}

BOOL I2C_SendAddArr(uint8 addr, uint8 regaddr, uint8* databuf, uint8 lenth)
{
	Start();

	if (SendByte((addr << 1) | 0x00))
		goto end;

	if (SendByte(regaddr))
		goto end;

	for (size_t i = 0; i < lenth; i++)
	{
		if (SendByte(databuf[i]))
			goto end;
	}

	End();
	return True;
end:
	End();
	return False;
}

BOOL I2C_ReadAddArr(uint8 addr, uint8 regaddr, uint8* databuf, uint8 lenth)
{
	Start();

	if (SendByte((addr << 1) | 0x00))
		goto end;

	if (SendByte(regaddr))
		goto end;

	Start();

	if (SendByte((addr << 1) | 0x01))
		goto end;

	for (size_t i = 0; i < lenth - 1; i++)
		databuf[i] = ReadByte(True);

	databuf[lenth - 1] = ReadByte(False);
	End();
	return True;
end:
	End();
	return False;
}